import { CodeEditorComponent } from '@farris/designer-devkit';
import { FormSchemaEntity, FormSchemaEntityField } from '@farris/designer-services';
import { BeforeOpenModalResult, ElementPropertyConfig } from '@farris/ide-property-panel';
import { DgControl } from '../../../../utils/dg-control';
import { EventsEditorFuncUtils } from '../../../../utils/events-editor-func';
import { CollectionProp } from '../../common/property/collection-property-config';
import { TemplateBindingEditorComponent } from './editor/template-binding-editor/template-binding-editor.component';

export class ListViewProp extends CollectionProp {


    getPropConfig(propertyData: any): ElementPropertyConfig[] {
        const viewModelId = this.viewModelId;
        const propertyConfig: ElementPropertyConfig[] = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData);
        propertyConfig.push(basicPropConfig);

        // 外观属性
        const appearancePropConfig = this.getAppearancePropConfig(propertyData, viewModelId);
        propertyConfig.push(appearancePropConfig);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, viewModelId);
        propertyConfig.push(behaviorPropConfig);

        // 事件属性
        const eventPropConfig = this.getEventPropConfig(propertyData, viewModelId);
        propertyConfig.push(eventPropConfig);

        // 分页属性
        const pagePropConfig = this.getPagePropConfig(propertyData, viewModelId);
        propertyConfig.push(pagePropConfig);


        return propertyConfig;
    }
    getBasicPropConfig(propertyData: any): ElementPropertyConfig {

        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: [
                {
                    propertyID: 'id',
                    propertyName: '标识',
                    propertyType: 'string',
                    description: '组件的id',
                    readonly: true
                },
                {
                    propertyID: 'type',
                    propertyName: '控件类型',
                    propertyType: 'select',
                    description: '组件的类型',
                    iterator: [{ key: propertyData.type, value: DgControl[propertyData.type].name }],
                    readonly: true
                }
            ]
        };
    }
    private getAppearancePropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const commonProps = this.getCommonAppearanceProperties();
        return {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: [
                ...commonProps,
                {
                    propertyID: 'listClassName',
                    propertyName: '列表自定义样式',
                    propertyType: 'string',
                    description: '列表自定义样式设置'
                },
                {
                    propertyID: 'headerTemplate',
                    propertyName: '头部Html模板',
                    propertyType: 'modal',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'html'
                    }
                },
                {
                    propertyID: 'contentTemplate',
                    propertyName: '主体Html模板',
                    propertyType: 'modal',
                    editor: TemplateBindingEditorComponent,
                    editorParams: {
                        listViewId: propertyData.id,
                        templateUri: 'assets/form/preset-template/listview-template.json',
                        schemaFields: this.getPanelMappingFields(propertyData),
                        viewModelId: this.viewModelId
                    },
                    beforeOpenModal(): BeforeOpenModalResult {
                        // 取字段最新值
                        this.editorParams.schemaFields = self.getPanelMappingFields(propertyData);
                        return { result: true, message: '' };
                    }
                },
                {
                    propertyID: 'footerTemplate',
                    propertyName: '底部Html模板',
                    propertyType: 'modal',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'html'
                    }
                }
            ]
        };
    }

    private getBehaviorPropConfig(propertyData: any, viewModelId: string) {
        return {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: [
                {
                    propertyID: 'fill',
                    propertyName: '填充',
                    propertyType: 'boolean',
                    description: '是否填充'
                },
                {
                    propertyID: 'cardLayout',
                    propertyName: '横向排列',
                    propertyType: 'boolean',
                    description: '是否横向排列',
                    defaultValue: false
                },
                {
                    propertyID: 'showEmpty',
                    propertyName: '空数据展示',
                    propertyType: 'boolean',
                    description: '数据为空时是否展示',
                    defaultValue: true
                },
                {
                    propertyID: 'emptyTemplate',
                    propertyName: '空数据时的展示模板',
                    propertyType: 'modal',
                    description: '数据为空时的展示模板',
                    visible: propertyData.showEmpty,
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'html'
                    }
                },
                {
                    propertyID: 'sortable',
                    propertyName: '允许排序',
                    propertyType: 'boolean',
                    description: '是否允许排序'
                },
                {
                    propertyID: 'sort',
                    propertyName: '排序字段',
                    propertyType: 'string',
                    description: '排序字段设置'
                },
                {
                    propertyID: 'multiSelect',
                    propertyName: '是否启用多选',
                    propertyType: 'boolean',
                    defaultValue: false
                }

            ],
            setPropertyRelates(changeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                if (changeObject.propertyID === 'showEmpty') {
                    const emptyTemplate = this.properties.find(p => p.propertyID === 'emptyTemplate');
                    if (emptyTemplate) {
                        emptyTemplate.visible = changeObject.propertyValue;
                    }
                }
            }
        };
    }

    private getEventPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const domService = this.domService;
        const webCmdService = this.webCmdService;
        const formBasicService = this.formBasicService;
        const eventEditorService = this.eventEditorService;
        let eventList = [
            {
                label: 'listClick',
                name: '行点击事件'
            }
        ];
        eventList = self.switchEvents(propertyData, eventList);
        return {
            categoryId: 'eventsEditor',
            categoryName: '事件',
            hideTitle: true,
            properties: EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList, self.switchEvents),
            tabId: 'commands',
            tabName: '交互',
            setPropertyRelates(changeObject, data, parameters) {
                delete propertyData[viewModelId];
                EventsEditorFuncUtils.saveRelatedParameters(eventEditorService,domService, webCmdService, propertyData, viewModelId, parameters['events'], parameters);
                this.properties = EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, parameters['events'], self.switchEvents);
            }
        };
    }
    private switchEvents(propertyData, eventList) {
        if (propertyData.supportPaging) {
            const eventListExist = eventList.find(eventListItem => eventListItem.label === 'pageChanged');
            if (!eventListExist) {
                eventList.push(
                    {
                        label: 'pageChanged',
                        name: '切换分页事件'
                    },
                    {
                        label: 'pageSizeChanged',
                        name: '每页显示条数变化事件'
                    });
            }
        } else {
            eventList = eventList.filter(eventListItem => eventListItem.label !== 'pageChanged' && eventListItem.label !== 'pageSizeChanged')
        }


        if (propertyData.multiSelect) {
            const eventListExist = eventList.find(eventListItem => eventListItem.label === 'checkChange');
            if (!eventListExist) {
                eventList.push(
                    {
                        label: 'checkChange',
                        name: '多选改变事件'
                    });
            }
        } else {
            eventList = eventList.filter(eventListItem => eventListItem.label !== 'checkChange');
        }

        return eventList;
    }

    private getPagePropConfig(propertyData: any, viewModelId: string) {
        const viewModel = this.domService.getViewModelById(viewModelId);
        if (!viewModel.pagination) {
            viewModel.pagination = {
                enable: false
            };
        }
        const vmPagination = viewModel.pagination;
        // 这三个属性是存在vm中，但是需要在datagrid控件上编辑
        // propertyData.supportPaging = vmPagination.enable;
        propertyData.pageList = vmPagination.pageList ? vmPagination.pageList : propertyData.pageList;
        propertyData.pageSize = vmPagination.pageSize ? vmPagination.pageSize : propertyData.pageSize;

        const pageSizeIterator = this.getPageSizeIterator(propertyData.pageList);
        const self = this;
        return {
            categoryId: 'page',
            categoryName: '分页',
            properties: [{
                propertyID: 'supportPaging',
                propertyName: '启用分页',
                propertyType: 'boolean',
                defaultValue: false,
                readonly: viewModel.bindTo !== '/'
            },
            {
                propertyID: 'showPageSize',
                propertyName: '显示分页条数',
                propertyType: 'boolean',
                description: '是否显示分页条数',
                visible: propertyData.supportPaging
            },
            {
                propertyID: 'pageList',
                propertyName: '分页条数',
                propertyType: 'string',
                description: '请输入以英文逗号分开的数字，最大值为1000。例如：10,20,30,50,100',
                visible: propertyData.supportPaging && propertyData.showPageSize,
                notAllowedChars: [/[^\d,]/g]
            },
            {
                propertyID: 'pageSize',
                propertyName: '默认分页条数',
                propertyType: 'select',
                description: '默认分页条数设置',
                iterator: pageSizeIterator,
                visible: propertyData.supportPaging
            },
            {
                propertyID: 'pageTemplate',
                propertyName: '分页导航模板',
                propertyType: 'modal',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'html'
                },
                visible: propertyData.supportPaging
            }],
            setPropertyRelates(changeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'supportPaging': {
                        this.properties.map(p => {
                            if (p.propertyID !== 'supportPaging') {
                                p.visible = changeObject.propertyValue;
                            }
                            if (p.propertyID === 'pageList') {
                                p.visible = changeObject.propertyValue && propertyData.showPageSize;
                            }
                        });
                        vmPagination.enable = changeObject.propertyValue;

                        if (changeObject.propertyValue) {
                            if (!propertyData.pageSize) {
                                propertyData.pageSize = 20;
                                vmPagination.pageSize = 20;
                            }
                            self.setDefaultPageList(propertyData, vmPagination);
                            const pageSize = this.properties.find(p => p.propertyID === 'pageSize');
                            if (pageSize) {
                                pageSize.iterator = self.getPageSizeIterator(propertyData.pageList);
                            }
                        }
                        break;
                    }
                    case 'pageList': {
                        vmPagination.pageList = changeObject.propertyValue;
                        const pageSize = this.properties.find(p => p.propertyID === 'pageSize');
                        if (pageSize) {
                            pageSize.iterator = self.getPageSizeIterator(changeObject.propertyValue);
                        }
                        if (!changeObject.propertyValue.includes(propertyData.pageSize)) {
                            vmPagination.pageSize = propertyData.pageSize = null;
                        }
                        break;
                    }
                    case 'pageSize': {
                        vmPagination.pageSize = changeObject.propertyValue;
                        break;
                    }
                    case 'showPageSize': {
                        const pageList = this.properties.find(p => p.propertyID === 'pageList');
                        if (pageList) {
                            pageList.visible = changeObject.propertyValue;
                        }

                        if (changeObject.propertyValue) {
                            self.setDefaultPageList(propertyData, vmPagination);
                            const pageSize = this.properties.find(p => p.propertyID === 'pageSize');
                            if (pageSize) {
                                pageSize.iterator = self.getPageSizeIterator(propertyData.pageList);
                            }

                            // 默认配置分页条数变化事件
                            if (!propertyData.pageSizeChanged) {
                                propertyData.pageSizeChanged = propertyData.pageChanged;
                            }


                        }


                    }
                }
            }
        };
    }
    getPageSizeIterator(pageList: string) {
        if (!pageList) {
            pageList = '10,20,30,50,100';
        }
        const iterator = [];
        pageList.split(',').forEach(pageSize => {
            iterator.push({
                key: Number.parseInt(pageSize, 10),
                value: pageSize
            });
        });
        return iterator;
    }

    private setDefaultPageList(propertyData: any, vmPagination: any) {

        if (!propertyData.pageList) {
            propertyData.pageList = '10,20,30,50,100';
            if (propertyData.pageSize && !propertyData.pageList.includes(propertyData.pageSize)) {
                let pageList = [10, 20, 30, 50, 100, propertyData.pageSize];
                pageList = pageList.sort((A, B) => A - B);
                propertyData.pageList = pageList.toString();
            }
            vmPagination.pageList = propertyData.pageList;
        }
    }

    private getPanelMappingFields(propertyData: any): FormSchemaEntityField[] {
        if (this.viewModelId) {
            const displayFieldsInViewModel = this.getDisplayFieldsInViewModel(this.viewModelId);
            return displayFieldsInViewModel;
        }
        return [];
    }

    /**
     * 获取当前视图模型对应实体中的所有字段
     * @param viewModelId 视图模型id
     */
    private getDisplayFieldsInViewModel(viewModelId: string): FormSchemaEntityField[] {
        const viewModel = this.domService.getViewModelById(viewModelId);
        if (!viewModel) {
            return [];
        }
        const entities = this.schemaService.getSchemaEntities();
        if (!entities || !entities.length) {
            return [];
        }
        const allFieldsInSpecialEntity = this._getSimpleTableFieldsByBindTo(entities, viewModel.bindTo);
        // const viewModelFieldsMap = new Map<string, boolean>();
        // viewModel.fields.forEach(field => viewModelFieldsMap.set(field.id, true));
        // const displayEntityFieldInViewModel = allFieldsInSpecialEntity.filter(field => viewModelFieldsMap.has(field.id));
        return allFieldsInSpecialEntity;
    }

    private _getSimpleTableFieldsByBindTo(entities: FormSchemaEntity[], bindTo: string): FormSchemaEntityField[] {
        if (!entities || entities.length === 0) {
            return;
        }
        const splitIndex = bindTo.indexOf('/');
        if (splitIndex > -1) {
            bindTo = bindTo.slice(splitIndex + 1, bindTo.length);
        }

        for (const entity of entities) {
            const entityType = entity.type;
            if (!entityType) {
                return [];
            }
            if (bindTo === '' || bindTo === entity.code || bindTo === entity.label) {
                return this.extractFieldsFromEntityType(entity.type);
            }
            if (entityType.entities && entityType.entities.length > 0) {
                const fields = this._getSimpleTableFieldsByBindTo(entityType.entities, bindTo);
                if (fields) {
                    return fields;
                }
            }
        }
    }
    private extractFieldsFromEntityType(entityType: { fields?: FormSchemaEntityField[] }) {
        const fields: FormSchemaEntityField[] = [];
        if (entityType && entityType.fields && entityType.fields.length) {
            entityType.fields.forEach(field => {
                if (field.$type === 'SimpleField') {
                    fields.push(field);
                } else {
                    const extractedFields = this.extractFieldsFromEntityType(field.type);
                    if (extractedFields.length) {
                        extractedFields.forEach(extractedField => fields.push(extractedField));
                    }
                }
            });
        }
        return fields;
    }
}
